﻿using ACS.SPiiPlusNET;
using Company.Axis;
using Company.Hardware.Acs;
using Company.Share.Events;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows;

namespace Company.UI.ViewModels
{
    public class PositioningAxisControlViewModel : BindableBase
    {
        #region 字段
        private bool _IsConnected;
        #endregion
        #region 属性
        public bool IsConnected 
        { 
            get=> _IsConnected;
            set 
            {
                _IsConnected = value;
                RaisePropertyChanged();
            }
        }
        public AcsControllerProvider AcsControllerProvider { get;private set; }
        public ObservableCollection<string> AxesCollection { get;private set; }
        //public AcsMotionAxis AcsMotionAxis { get;private set; }
        private AcsMotionAxis _AcsMotionAxis;

        public AcsMotionAxis AcsMotionAxis
        {
            get { return _AcsMotionAxis; }
            set { _AcsMotionAxis = value; RaisePropertyChanged(); }
        }

        public int CurrentAxisId => AcsMotionAxis.AxisParameter.CurrentAxisId;
        public MotorStates AxisState => AcsControllerProvider.AcsController.GetMotorStates((ACS.SPiiPlusNET.Axis)CurrentAxisId);
        #endregion
        #region Commands
        public DelegateCommand AxisEnableCommand { get;}
        public DelegateCommand AxisDisableCommand { get;}
        //public DelegateCommand AxisReferenceCommand { get; set; }
        public DelegateCommand AxisSwitchSoftwareLimitCommand { get;}
        public DelegateCommand AxisSwitchHardwareLimitCommand { get;}
        //public DelegateCommand AxisCoupleSubAxisCommand { get; set; }
        public DelegateCommand<object> AxisMoveByJoggingCommand { get;}
        public DelegateCommand AxisMoveByAbsoluteCommand { get;}
        public DelegateCommand AxisMoveByRelativeCommand { get;}
        public DelegateCommand AxisStopCommand { get;}
        public DelegateCommand AxesStoppedAllCommand { get;}
        public DelegateCommand<object> AxisSelectionChangedCommand { get;}
        public DelegateCommand<object> SetMotionParameterCommand { get;}
        //public DelegateCommand ControllerRebootCommand { get; set; }
        public DelegateCommand SetAxisZeroPositionCommand { get;}
        public DelegateCommand<object> UserControlLoadedCommand { get;}

        #endregion
        public PositioningAxisControlViewModel(AcsControllerProvider acsControllerProvider,
                                                IEventAggregator eventAggregator)
        {
            AcsControllerProvider = acsControllerProvider;

            AxesCollection = new ObservableCollection<string>();
            AxisEnableCommand = new DelegateCommand(AxisEnable);
            AxisDisableCommand = new DelegateCommand(AxisDisable);
            //AxisReferenceCommand = new DelegateCommand(AxisReference);//该功能已移除此页面
            AxisSwitchSoftwareLimitCommand = new DelegateCommand(AxisSwitchSoftwareLimit);
            AxisSwitchHardwareLimitCommand = new DelegateCommand(AxisSwitchHardwareLimit);
            //AxisCoupleSubAxisCommand = new DelegateCommand(AxisCoupleSubAxis);//该功能已移除此页面
            AxisMoveByJoggingCommand = new DelegateCommand<object>(AxisMoveByJogging);
            AxisMoveByAbsoluteCommand = new DelegateCommand(AxisMoveByAbsolute);
            AxisMoveByRelativeCommand = new DelegateCommand(AxisMoveByRelative);
            AxisStopCommand = new DelegateCommand(AxisStop);
            AxesStoppedAllCommand = new DelegateCommand(AxesStoppedAll);
            AxisSelectionChangedCommand = new DelegateCommand<object>(AxisSelectionChanged);
            SetMotionParameterCommand = new DelegateCommand<object>(SetMotionParameter);
           // ControllerRebootCommand = new DelegateCommand(ControllerReboot);//该功能已移除此页面
            SetAxisZeroPositionCommand = new DelegateCommand(SetAxisZeroPosition);
            UserControlLoadedCommand = new DelegateCommand<object>(UserControlLoaded);
            // 使用事件聚合器订阅
            eventAggregator.GetEvent<AcsControllerConnectedEvent>().Subscribe((obj) =>
            {
                IsConnected = obj;
                if (IsConnected)
                {
                    AxesCollection.Clear();
                    var axesCount = Convert.ToInt32(AcsControllerProvider.AcsController.AxesCount);
                    for (int i = 0; i < axesCount; i++)
                    {
                        AxesCollection.Add(i.ToString());
                    }
                }
            });
        }
        /// <summary>
        /// 用户控件加载事件
        /// </summary>
        /// <param name="obj"></param>
        private void UserControlLoaded(object obj)
        {
            AcsMotionAxis acsMotionAxis = (AcsMotionAxis)obj;
            AcsMotionAxis = acsMotionAxis;
        }
        /// <summary>
        /// 轴使能
        /// </summary>
        private void AxisEnable()
        {
            if ((AxisState & MotorStates.ACSC_MST_ENABLE) == 0) 
                AcsControllerProvider.AcsController.Enable((ACS.SPiiPlusNET.Axis)CurrentAxisId);
        }
        /// <summary>
        /// 轴断使能
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void AxisDisable()
        {
            if ((AxisState & MotorStates.ACSC_MST_ENABLE) != 0) 
                AcsControllerProvider.AcsController.Disable((ACS.SPiiPlusNET.Axis)CurrentAxisId);
        }
        /// <summary>
        /// 轴切换软限位
        /// </summary>
        private void AxisSwitchSoftwareLimit()
        {

            if (!AcsControllerProvider.AcsController.IsConnected) return;
            if (AcsMotionAxis.AxisState.IsSoftwareLimitActivated)
            {
                AcsControllerProvider.AcsController.DisableFault((ACS.SPiiPlusNET.Axis)CurrentAxisId, SafetyControlMasks.ACSC_SAFETY_SLL);
                AcsControllerProvider.AcsController.DisableFault((ACS.SPiiPlusNET.Axis)CurrentAxisId, SafetyControlMasks.ACSC_SAFETY_SRL);
                AcsMotionAxis.AxisState.IsSoftwareLimitActivated = false;
                return;
            }
            if (!AcsMotionAxis.AxisState.IsSoftwareLimitActivated)
            {
                AcsControllerProvider.AcsController.EnableFault((ACS.SPiiPlusNET.Axis)CurrentAxisId, SafetyControlMasks.ACSC_SAFETY_SLL);
                AcsControllerProvider.AcsController.EnableFault((ACS.SPiiPlusNET.Axis)CurrentAxisId, SafetyControlMasks.ACSC_SAFETY_SRL);
                AcsMotionAxis.AxisState.IsSoftwareLimitActivated = true;
                return;
            }

        }
        /// <summary>
        /// 轴切换硬限位
        /// </summary>
        private void AxisSwitchHardwareLimit()
        {
            if (!AcsControllerProvider.AcsController.IsConnected) return;
            if (AcsMotionAxis.AxisState.IsHardwareLimitActivated)
            {
                AcsControllerProvider.AcsController.DisableFault((ACS.SPiiPlusNET.Axis)CurrentAxisId, SafetyControlMasks.ACSC_SAFETY_LL);
                AcsControllerProvider.AcsController.DisableFault((ACS.SPiiPlusNET.Axis)CurrentAxisId, SafetyControlMasks.ACSC_SAFETY_RL);
                return;
            }
            if (!AcsMotionAxis.AxisState.IsHardwareLimitActivated)
            {
                AcsControllerProvider.AcsController.EnableFault((ACS.SPiiPlusNET.Axis)CurrentAxisId, SafetyControlMasks.ACSC_SAFETY_LL);
                AcsControllerProvider.AcsController.EnableFault((ACS.SPiiPlusNET.Axis)CurrentAxisId, SafetyControlMasks.ACSC_SAFETY_RL);
                return;
            }
        }
        /// <summary>
        /// 轴Jog运动
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void AxisMoveByJogging(object obj)
        {
            var jogDirection = obj as string;
            if (string.IsNullOrEmpty(jogDirection)) return;
            AxisEnable();
            var axisVelocity = Math.Abs(AcsMotionAxis.AxisParameter.TargetVelocity);
            AcsControllerProvider.AcsController.Halt((ACS.SPiiPlusNET.Axis)CurrentAxisId);
            switch (jogDirection)
            {
                case "JogMinus":
                    AcsControllerProvider.AcsController.Jog(MotionFlags.ACSC_AMF_VELOCITY, (ACS.SPiiPlusNET.Axis)CurrentAxisId, -axisVelocity);
                    break;
                case "JogPlus":
                    AcsControllerProvider.AcsController.Jog(MotionFlags.ACSC_AMF_VELOCITY, (ACS.SPiiPlusNET.Axis)CurrentAxisId, axisVelocity);
                    break;
                default:
                    AcsControllerProvider.AcsController.Jog(MotionFlags.ACSC_AMF_VELOCITY, (ACS.SPiiPlusNET.Axis)CurrentAxisId, 0.0);
                    break;
            }
        }
        /// <summary>
        /// 轴绝对运动
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void AxisMoveByAbsolute()
        {
            AxisEnable();
            var targetPosition = AcsMotionAxis.AxisParameter.TargetPosition;
            AcsControllerProvider.AcsController.ToPoint(MotionFlags.ACSC_NONE, (ACS.SPiiPlusNET.Axis)CurrentAxisId, targetPosition);
        }
        /// <summary>
        /// 轴相对运动
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void AxisMoveByRelative()
        {
            AxisEnable();
            var targetPosition = AcsMotionAxis.AxisParameter.TargetPosition;
            AcsControllerProvider.AcsController.ToPoint(MotionFlags.ACSC_AMF_RELATIVE, (ACS.SPiiPlusNET.Axis)CurrentAxisId, targetPosition);
        }
        /// <summary>
        /// 轴停止
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void AxisStop()
        {
            AcsControllerProvider.AcsController.Halt((ACS.SPiiPlusNET.Axis)CurrentAxisId);
        }
        /// <summary>
        /// 停止所有轴
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void AxesStoppedAll()
        {
            // 任何情况下，都可一键停止，即使没有连接状态下。
            ACS.SPiiPlusNET.Axis[] axes = AxesCollection.Select(axis => (ACS.SPiiPlusNET.Axis)Enum.Parse(typeof(ACS.SPiiPlusNET.Axis), axis)).ToArray();
            //AcsController.AcsInstance.HaltM(axes);
            AcsControllerProvider.AcsController.KillAllAxes();
        }
        /// <summary>
        /// 轴号选择发生改变事件处理
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void AxisSelectionChanged(object obj)
        {
            AcsMotionAxis.AxisParameter.CurrentAxisId = Convert.ToInt16(obj);
            // 更新数据
            AcsMotionAxis.AxisParameter.TargetSoftLeftLimit = (double)AcsControllerProvider.AcsController.ReadVariable("SLLIMIT", ProgramBuffer.ACSC_NONE, CurrentAxisId, CurrentAxisId);
            AcsMotionAxis.AxisParameter.TargetSoftRightLimit = (double)AcsControllerProvider.AcsController.ReadVariable("SRLIMIT", ProgramBuffer.ACSC_NONE, CurrentAxisId, CurrentAxisId);
            // 获取当前加速度
            AcsMotionAxis.AxisParameter.TargetAcceleration = (double)AcsControllerProvider.AcsController.AcsInstance.GetAcceleration((ACS.SPiiPlusNET.Axis)CurrentAxisId);
            // 获取当前减速度
            AcsMotionAxis.AxisParameter.TargetDeceleration = (double)AcsControllerProvider.AcsController.AcsInstance.GetDeceleration((ACS.SPiiPlusNET.Axis)CurrentAxisId);
            // 获取加加速
            AcsMotionAxis.AxisParameter.TargetJerk = (double)AcsControllerProvider.AcsController.AcsInstance.GetJerk((ACS.SPiiPlusNET.Axis)CurrentAxisId);
            // 获取急停减速度
            AcsMotionAxis.AxisParameter.TargetKillDeceleration = (double)AcsControllerProvider.AcsController.GetKillDeceleration((ACS.SPiiPlusNET.Axis)CurrentAxisId);
           
        }
        /// <summary>
        /// 设置运动参数
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void SetMotionParameter(object obj)
        {
            if (!AcsControllerProvider.AcsController.IsConnected) return;
            var nameOfObject = obj as string;
            if (nameOfObject == null) return;
            switch (obj)
            {
                case "Target Velocity":
                    AcsControllerProvider.AcsController.AcsInstance.SetVelocity((ACS.SPiiPlusNET.Axis)CurrentAxisId, AcsMotionAxis.AxisParameter.TargetVelocity);
                    break;
                case "Target Acceleration":
                    AcsControllerProvider.AcsController.AcsInstance.SetAcceleration((ACS.SPiiPlusNET.Axis)CurrentAxisId, AcsMotionAxis.AxisParameter.TargetAcceleration);
                    break;
                case "Target Deceleration":
                    AcsControllerProvider.AcsController.AcsInstance.SetDeceleration((ACS.SPiiPlusNET.Axis)CurrentAxisId, AcsMotionAxis.AxisParameter.TargetDeceleration);
                    break;
                case "Target KillDeceleration":
                    AcsControllerProvider.AcsController.AcsInstance.SetKillDeceleration((ACS.SPiiPlusNET.Axis)CurrentAxisId, AcsMotionAxis.AxisParameter.TargetKillDeceleration);
                    break;
                case "Target Jerk":
                    AcsControllerProvider.AcsController.AcsInstance.SetJerk((ACS.SPiiPlusNET.Axis)CurrentAxisId, AcsMotionAxis.AxisParameter.TargetJerk);
                    break;
                case "Target SLLIMIT":
                    AcsControllerProvider.AcsController.WriteVariable(AcsMotionAxis.AxisParameter.TargetSoftLeftLimit, "SLLIMIT", ProgramBuffer.ACSC_NONE, CurrentAxisId, CurrentAxisId);
                    break;
                case "Target SRLIMIT":
                    AcsControllerProvider.AcsController.WriteVariable(AcsMotionAxis.AxisParameter.TargetSoftRightLimit, "SRLIMIT", ProgramBuffer.ACSC_NONE, CurrentAxisId, CurrentAxisId);
                    break;
            }
        }
        /// <summary>
        /// 设置位置清零
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void SetAxisZeroPosition()
        {
            AcsControllerProvider.AcsController.AcsInstance.SetFPosition((ACS.SPiiPlusNET.Axis)CurrentAxisId, 0.0);
        }
    }
}
